
/**
  ******************************************************************************
  * @file    stringx.c
  * @author  Dragon.Chen
  * @version V1.5.0
  * @date    04-27-2013
  * @brief   字符串高级操作函数接口
  * @project linux client
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 上海今中网络科技有限公司 </center></h2>
  ******************************************************************************
  */

#include "stringx.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


/// 声明一个函数，这里是因为递归调用的问题进行声明
static int match_here(char *regexp, char *text);

/**
  * @brief      判断字符串是否以指定字符串开始
  * @param      arg1、源字符串；arg2、子字符串
  * @retval     1、是以指定字符串开始；0、不是；-1、子字符串超越源字符串长度
  */
int start_with(const char *ptr_src, const char *start_str)
{
    size_t len;

	if (ptr_src == NULL || start_str == NULL)
		return 0;
    len = strlen(start_str);
    if(strlen(ptr_src) < len)
		return -1;
    if (!strncmp(ptr_src, start_str, len))
		return 1;
    return 0;
}


/**
  * @brief      判断字符串是否以指定字符串结束
  * @param      arg1、源字符串；arg2、子字符串
  * @retval     1、是以指定字符串结束；0、不是；-1、子字符串超越源字符串长度
  */
int end_with(const char *ptr_src, const char *end_str)
{
    int len1, len2;

	if (ptr_src == NULL || end_str == NULL)
		return 0;
    len1 = strlen(ptr_src);
    len2 = strlen(end_str);
    if (len1 < len2)
		return -1;
    if (!strncmp(ptr_src+len1-len2, end_str, len2))
		return 1;
    return 0;
}


/**
  * @brief      截取指定字符后的最后字符串
  * @param      arg1、最后字符串；arg2、源字符串；arg3、拆分符
  * @retval     最后字符串
  * @attention  src必须是字符串数组
  */
char *get_last_str_by_token(char *last_str, char *src, const char *token)
{
    char *temp = NULL;

	if (last_str == NULL || src == NULL || token == NULL)
		return NULL;
    temp = strtok(src, token);
    while(temp != NULL)
    {
        strcpy(last_str, temp);
        temp = strtok(NULL, token);
    }
    return last_str;
}

/**
  * @brief      截取指定字符后的第一个字符串
  * @param      arg1、最后字符串；arg2、源字符串；arg3、拆分符
  * @retval     最后字符串
  * @attention  src必须是字符串数组
  */
char *get_first_str_by_token(char *first_str, char *src, const char *token)
{
	if (first_str == NULL || src == NULL || token == NULL)
		return NULL;

    first_str = strtok(src, token);
    return first_str;
}

/**
  * @brief      获取src前len个长度字符数组中指定字符出现的次数
  * @param      arg1、源字符串；arg2、待检测的字符；arg3、指定的长度
  * @retval     返回指定字符出现的次数, 出错返回-1
  */
int get_count_specified_char(const char *src, const char ch, int len)
{
    int i, cnt=0;

	if (src == NULL)
		return -1;
    if (len > (int)strlen(src))
		return -1;
    for (i=0; i<len; i++)
    {
        if(src[i] == ch)
            cnt++;
    }
    return cnt;
}


/**
  * @brief      用于判断目标字符串是否是源字符串子字符串(首次出现的位置)
  * @param      arg1、源字符串；arg2、待检测的字符
  * @retval     是返回1，否则返回-1
  */
int contains(const char *source, const char *target)
{
	if (source == NULL || target == NULL)
		return -1;
	if (strstr(source, target) != NULL)
		return 1;
    return -1;
}


/**
  * @brief      源字符串包含目标字符串的次数
  * @param      arg1、源字符串；arg2、待检测的字符
  * @retval     正常返回包含的次数(>0)，否则返回-1
  */
int containc(const char *src, const char *dst)
{
    int cnt = 0;
    char *last = (char*)src;

    if (src == NULL || dst == NULL)  return -1;
    while ( (last = strstr(last, dst)) != NULL)
    {
        last += 1;
        cnt++;
    }

    return cnt;
}


/**
  * @brief      获取子字符串
  * @param      arg1、目标字符串； arg2、 目标字符串大小 arg3、源字符串；arg4、字符串开始位置；arg5字符串结束位置
  * @retval     成功返回子字符串，失败返回NULL
  */
char *substr(char *dst, int size, const char *src, int begin, int end)
{
	int len;

	if (dst == NULL || src == NULL)
		return NULL;
    len = strlen(src);
	if (begin < 0)
		begin = 0;
	if ((end - begin) < 0)
		return NULL;
    if (len < end)
		return NULL;
    memset(dst, 0, size);
    strncpy(dst, src+begin-1, (end-begin+1) >= size ? (size-1) : (end-begin+1));
    return dst;
}


/**
  * @brief      获取子字符串
  * @param      arg1、目标字符串 arg2、 目标字符串大小  arg3、源字符串；arg4、字符串开始位置
  * @retval     成功返回子字符串，失败返回NULL
  */
char *substr_by_start_position(char *dst, int size, const char *src, int begin)
{
	int len;

	if (dst == NULL || src == NULL)
		return NULL;
    len = strlen(src);
	if (begin < 0)
		begin = 0;
    if (len < begin)
		return NULL;
    memset(dst, 0, size);
    strncpy(dst, src+begin-1, (len-begin+1) >= size ? (size-1) : (len-begin+1));
    return dst;
}


/**
  * @brief      去除字符串的首尾空格和回车
  * @param      arg1、目标字符串  arg2、 目标字符串大小  arg3、源字符串
  * @retval     成功返回去除空格的字符串
  * @attention  如果处理完成的字符串大于提供的缓冲区大小时，返回缓冲区大小的字符串
  */
char *trim(char *dst, int size, const char *src)
{
	int st = 0;
	int len;

	if (dst == NULL || src == NULL)
		return NULL;
	len = strlen(src);
    while ((st < len) && (src[st] == ' '))  		//去除前空格 while ((st < len) && (src[st] < ' '))
            st++;
    while ((st < len) && (src[len - 1] == ' '))		//去除后空格
            len--;
    memset(dst, 0, size);
    strncpy(dst, src+st, (len-st) >= size ? (size-1) : (len-st));
    return dst;
}

/**
  * @brief      去除字符串的首尾空格和回车
  * @param      arg1、待处理字符串
  * @retval     成功返回去除空格的字符串
  */
  /* 与config-util.c冲突了
void trim2(char *src)
{
    char *start = src;
	char* end;

	while ( (*start == ' ') || (*start == '\t') )
	{
		start++;
	}

	if (strlen(start) == 0)
	{
		return;
	}

	end = src + strlen(src) - 1;
	while ( (*end == ' ') || (*end == '\t') )
	{
		*end = 0;
		end--;
	}

	if ( ((int)(end - start) + 1) <= 0 )
	{
		return;
	}

    memmove(src, start, strlen(start)+1);
}
*/
/**
  * @brief    去除最后个\n字符
  * @param	  arg:字符串，修改后直接使用buf字符串
  * @retval
  */
void str_del_enter(char *buf)
{
	if (buf[strlen(buf)-1] == '\n')
    {
		buf[strlen(buf)-1]=0;
	}
}

/**
  * @brief
  * @param
  * @retval
  */
static int match_star(char *regexp, char *text)
{
    int i;
	if ( regexp[0]=='\0' )
		return 1;
	for(i=1;i<=strlen(text);i++)
    {
		//星号要从后面比对，比如regexp: a*b,text:aabcbb应该是对的，但从头比对就会得到错误结果，因为到了第一个b就比对结束了
		//strlen(text)-i就是/0的前个字符（最后个字符)
		if ( regexp[0] == text[strlen(text)-i] )
		{
			return match_here(regexp+1,text+(strlen(text)-i+1));
		}
	}
	return 0;
}


/**
  * @brief
  * @param
  * @retval
  */
static int match_here(char *regexp, char *text)
{
	//如果到最后了就返回1
   if (regexp[0] == '\0' && text[0] == '\0')
   {
	   return 1;
   }
   if (regexp[0] == '*')
   {
	   return match_star(regexp+1, text);
   }
   //$符号
   /*if (regexp[0] == '$' && regexp[1] == '\0'){
	   return *text == '\0';
   }*/
   //?号和对比普通的对比
   if (*text!='\0' && (regexp[0]=='?' || regexp[0]==*text)){
	   return match_here(regexp+1, text+1);
   }
   return 0;
}

int match(char *regexp, char *text) {
	return match_here(regexp,text);
}


/**
  * @brief      字符串替换函数,能替换所有的要替换的字符串,被替换的字符串和替换的字符串不一定一样长.
  * @param      pDstOut,输出字符串 pSrcIn,输入字符串 pSrcRpl,被替换的字符串 pDstRpl,替换后的字符串
  * @retval
  * @note        pDstOut,输出字符串,要保证足够的空间可以存储替换后的字符串.以上的字符串均要以 '\0 '结尾.
  */
void str_rpl(char* pDstOut, char* pSrcIn, const char* pSrcRpl, const char* pDstRpl)
{
	char* pi = pSrcIn;
	char* po = pDstOut;
	int nSrcRplLen = strlen(pSrcRpl);
	int nDstRplLen = strlen(pDstRpl);
	char *p = NULL;
	int nLen = 0;

	do
	{
		// 找到下一个替换点
		p = strstr(pi, pSrcRpl);

		if(p != NULL)
		{
			// 拷贝上一个替换点和下一个替换点中间的字符串
			nLen = p - pi;
			memcpy(po, pi, nLen);

			// 拷贝需要替换的字符串
			memcpy(po + nLen, pDstRpl, nDstRplLen);
		}
		else
		{
			strcpy(po, pi);

			// 如果没有需要拷贝的字符串,说明循环应该结束
			break;
		}

		pi = p + nSrcRplLen;
		po = po + nLen + nDstRplLen;

	} while (p != NULL);
}



//****************patched by yagamishi add*************2016/02/11*******
/**
  * @brief    得到最后个字符串
  * @param	  arg1:源字符串 arg2:分割符 arg3最后得到的字符串
  * @retval
  */
void get_last_str(char * src,char * token,char *last_str){
	char *temp = NULL;
	char *srcCp = NULL;
	srcCp = (char *)calloc(strlen(src)+1, sizeof(char *));
	strcpy(srcCp,src);
	temp = strtok(srcCp, token);
	while(temp != NULL)
    {
		strcpy(last_str, temp);
        temp = strtok(NULL, token);
    }
	free(srcCp);
}
//***********************************************************************


/**
  * @brief  通配符匹配算法
  * @param  src,字符串 pattern,有通配符( * 或 ? 号)的字符串 ignore_case,是否区分大小写,1表示不区分,0表示区分
  * @retval 1,表示匹配 0,表示不匹配
  */
int wild_char_match(char *src, char *pattern, int ignore_case)
{
    int result;
    while (*src)
    {
        if (*pattern == '*')
        {   /* 如果 pattern 的当前字符是 '*' */
            /* 如果后续有多个 '*', 跳过 */
            while ((*pattern == '*') || (*pattern == '?'))
                    pattern++;
            /* 如果 '*" 后没有字符了，则正确匹配 */
            if (!*pattern) return MATCH;
            /* 在 src 中查找一个与 pattern中'*"后的一个字符相同的字符*/
            while (*src && (!MATCH_CHAR(*src,*pattern,ignore_case)))
                    src++;
            /* 如果找不到，则匹配失败 */
            if (!*src) return NOT_MATCH;
            /* 如果找到了，匹配剩下的字符串*/
            result = wild_char_match (src, pattern, ignore_case);
            /* 如果剩下的字符串匹配不上，但src后一个字符等于pattern中'*"后的一个字符 */
            /* src前进一位，继续匹配 */
            while ( (!result) && (*(src+1)) && MATCH_CHAR(*(src+1),*pattern,ignore_case) )
                result = wild_char_match (++src, pattern, ignore_case);
            return result;
        }
        else
        {
            /* 如果pattern中当前字符不是 '*' */
            /* 匹配当前字符*/
            if ( MATCH_CHAR(*src,*pattern,ignore_case) || ('?' == *pattern))
            {
            /* src,pattern分别前进一位，继续匹配 */
				return wild_char_match (++src, ++pattern, ignore_case);
            }
            else
            {
                return NOT_MATCH;
            }
        }
    }
    /* 如果src结束了，看pattern有否结束*/
    if (*pattern)
	{
	/* pattern没有结束*/
		if ( (*pattern=='*') && (*(pattern+1)==0) ) /* 如果pattern有最后一位字符且是'*' */
			return MATCH;
		else
			return NOT_MATCH;
	}
	else
        return MATCH;
}


//************************************************************************

/******************* (C) COPYRIGHT 2013 上海今中网络科技有限公司 *****END OF FILE****/

